home *** CD-ROM | disk | FTP | other *** search
/ SGI Freeware 1998 June / SGI Freeware 1998 June.iso / dist / fw_UMINNgopher.idb / usr / freeware / src / gopher_1.12 / gopher / manager.c.z / manager.c
C/C++ Source or Header  |  1997-09-09  |  11KB  |  468 lines

  1. /********************************************************************
  2.  * $Author: drich $
  3.  * $Revision: 1.1 $
  4.  * $Date: 1995/10/03 04:08:12 $
  5.  * $Source: /proj/freeware1.0/gopher1.12/src/gopher/RCS/manager.c,v $
  6.  * $State: Exp $
  7.  *
  8.  * Paul Lindner, University of Minnesota CIS.
  9.  *
  10.  * Copyright 1991, 1992 by the Regents of the University of Minnesota
  11.  * see the file "Copyright" in the distribution for conditions of use.
  12.  *********************************************************************
  13.  * MODULE: manager.c
  14.  * Procedures to manage the screen.
  15.  *********************************************************************
  16.  * Revision History:
  17.  * $Log: manager.c,v $
  18.  * Revision 1.1  1995/10/03  04:08:12  drich
  19.  * gopher 1.2 check-in
  20.  *
  21.  * Revision 1.3  1993/01/06  21:01:40  lindner
  22.  * Improved behaviour when executing an item by typing it's number
  23.  * The arrow and screen are updated to reflect the item being
  24.  * retrieved.
  25.  *
  26.  * Revision 1.2  1993/01/05  22:31:57  lindner
  27.  * Fixed display problems with directory title searching.
  28.  *
  29.  * Revision 1.1  1992/12/10  23:32:16  lindner
  30.  * gopher 1.1 release
  31.  *
  32.  * Revision 1.1  1992/12/10  06:16:51  lindner
  33.  * Initial revision
  34.  *
  35.  *
  36.  *********************************************************************/
  37.  
  38. #include "gopher.h"
  39.  
  40. #define MENULINE(x)   (x)+3
  41.  
  42. /* If any gophers to display (screen can be blank), count the number
  43.    of pages.  If there is a remainder greater than zero, add one page */
  44. #define PAGECALC(x,y) (y) ? (x/y) + ((x%y)>0) : 1
  45.  
  46.  
  47.  
  48. /*
  49. ** Draw the title on the top
  50. */
  51.  
  52. void
  53. Draw_Banner()
  54. {
  55.      standout();
  56.      CURcenterline(CursesScreen,VERSIONline, 0);
  57.      standend();
  58. }     
  59.  
  60.  
  61. /*
  62. ** Draw the status line
  63. */
  64.  
  65. void
  66. Draw_Status(textline)
  67.   char *textline;
  68. {
  69.      move(LINES-1, 0);
  70.      clrtoeol();
  71.      mvaddstr(LINES-1, 0, "Press ");
  72.      standout();
  73.      addstr("?");
  74.      standend();
  75.  
  76.      addstr(" for Help, ");
  77.  
  78.      standout();
  79.      addstr("q");
  80.      standend();
  81.      addstr(" to Quit, ");
  82.      
  83.      standout();
  84.      addstr("u");
  85.      standend();
  86.      addstr(" to go up a menu");
  87.      clrtoeol();
  88.  
  89.      mvaddch(LINES-1,  COLS-strlen(textline)-2, ' ');
  90.      addstr(textline);
  91. }
  92.  
  93.  
  94.  
  95. /*
  96. ** Man is this ugly.
  97. */
  98.  
  99. void
  100. Display_Dir_Page(gopherdir, iNewLine, nNewPage, nMaxPages, iPageLen, iLastPageLen)
  101.   GopherDirObj *gopherdir;
  102.   int iNewLine;
  103.   int nNewPage, nMaxPages, iPageLen, iLastPageLen;
  104. {
  105.      int i, iLoop, iOffset;
  106.      char temp[1024];
  107.      char *c, *d;
  108.      int m, n, type, max;
  109.  
  110.      /*** Clear the screen and redraw the top line **/
  111.      clear();
  112.      Draw_Banner();
  113.  
  114.      /** Draw the menu **/
  115.      iLoop = (nNewPage == nMaxPages) && iLastPageLen ? iLastPageLen : iPageLen;
  116.  
  117.      for (i= 0, iOffset = (nNewPage-1) * iPageLen; i <iLoop; i++, iOffset++) {
  118.       move(MENULINE(i+1), 6);
  119.       printw("%d.", iOffset +1);
  120.       if (iOffset + 1 < 10)
  121.            addch(' ');
  122.  
  123.       
  124.        type = GSgetType(GDgetEntry(gopherdir,iOffset));
  125.        d = GSgetTitle(GDgetEntry(gopherdir,iOffset));
  126.        max = COLS - 13;
  127.        switch(type)
  128.           {
  129.           case A_DIRECTORY:
  130.           case A_FILE:
  131.             max--;
  132.             break;
  133.               case A_SOUND:
  134.             max -= 3;
  135.             break;
  136.           case A_INDEX:
  137.             max -=4;
  138.             break;
  139.               case A_CSO:
  140.               case A_TN3270:
  141.           case A_TELNET:
  142.             case A_UNIXBIN:
  143.             case A_MACHEX:
  144.             max -=6;
  145.             break;
  146.              case A_PCBIN:
  147.             max -=9;
  148.             break;
  149.             case A_GIF:
  150.           case A_IMAGE:
  151.             max -= 10;
  152.             break;
  153.  
  154.               }
  155.  
  156.        if((m = strlen(d)) <= max)
  157.             printw(" %s", d);
  158.        else {
  159.            /*** Cut out the middle bits **/
  160.             if ((c = strchr(d, '/'))!=NULL && (max > (c-d))) {
  161.             n = c - d;
  162.              strncpy(temp, d, n);
  163.              strcpy(temp + n, "..");
  164.              strcat(temp, d + (m + n - max));
  165.              printw(" %s", temp);
  166.             } else {
  167.             /** Trunc it.. **/
  168.             strcpy(temp, d);
  169.             temp[max] ='\0';
  170.              printw(" %s..", temp);
  171.            }
  172.         }
  173.  
  174.       switch(type)
  175.          {
  176.          case A_DIRECTORY:
  177.            addch('/');
  178.            break;
  179.              case A_CSO:
  180.            addstr(" <CSO>");
  181.            break;
  182.              case A_TN3270:
  183.            addstr(" <3270>");
  184.            break;
  185.          case A_TELNET:
  186.            addstr(" <TEL>");
  187.            break;
  188.          case A_INDEX:
  189.            addstr(" <?>");
  190.            break;
  191.              case A_SOUND:
  192.            addstr(" <)");  /** It's supposed to look like a speaker! **/
  193.            break;
  194.          case A_FILE:
  195.            addch('.');
  196.            break;
  197.             case A_PCBIN:
  198.            addstr(" <PC Bin>");
  199.            break;
  200.            case A_UNIXBIN:
  201.            addstr(" <Bin>");
  202.            break;
  203.  
  204.          case A_IMAGE:
  205.              case A_GIF:
  206.            addstr(" <Picture>");
  207.            break;
  208.            case A_MACHEX:
  209.            addstr(" <HQX>");
  210.            break;
  211.  
  212.              }
  213.      }
  214. }
  215.  
  216.  
  217. /* scline - Screen line relocator.
  218.  *          Returns the line resulting from choice */
  219. int 
  220. scline( iOldGopher, iNewGopher, gophersdir)
  221.   int iOldGopher;     /* Which gopher previously displayed */
  222.   int iNewGopher;     /* New gopher to be displayed */
  223.   GopherDirObj  *gophersdir;
  224. {
  225.      int iPageLen, iLastPageLen;        /* Length of normal, final pages */
  226.      int nMaxPages, nNewPage, nOldPage; /* Natural numbers */
  227.      int iOldLine, iNewLine;            /* Screen locations */
  228.      char sPagenum[40];
  229.      int iMaxGophers;
  230.      
  231.      iMaxGophers = GDgetNumitems(gophersdir);
  232.  
  233.      if (iNewGopher==0)
  234.       iNewGopher = GDgetNumitems(gophersdir);
  235.  
  236.      if ((iNewGopher > iMaxGophers))
  237.       iNewGopher = 1;
  238.      
  239.      iPageLen = LINES-6;    /* Number of menu lines possible per page */
  240.      
  241.      nMaxPages = PAGECALC(iMaxGophers, iPageLen);    /* Total number of pages */
  242.      nOldPage =  PAGECALC(iOldGopher, iPageLen); 
  243.      nNewPage =  PAGECALC(iNewGopher, iPageLen);
  244.      
  245.      if ((nNewPage < 1) || (nNewPage > nMaxPages))   /* It won't work , make*/
  246.       return(iOldGopher);                          /* no changes */
  247.      
  248.     iLastPageLen = iMaxGophers % iPageLen;
  249.  
  250.     /* Lines on last page */
  251.  
  252.      iOldLine = iOldGopher - ((nOldPage-1)*iPageLen);/* Old Screen location */
  253.      iNewLine = iNewGopher - ((nNewPage-1)*iPageLen);/* New Screen location */
  254.      
  255.      if ((iNewLine < 0) || (iNewLine > iPageLen))
  256.       return(iOldGopher);
  257.      
  258.      if (nOldPage != nNewPage)    {
  259.     Display_Dir_Page(gophersdir,
  260.                         iNewLine, nNewPage, nMaxPages, iPageLen, iLastPageLen);
  261.     CURcenterline(CursesScreen,GDgetTitle(gophersdir), 2);       /*** Draw the title ***/
  262.    }
  263.     
  264.  
  265.      sprintf(sPagenum, "  Page: %d/%d", nNewPage, nMaxPages);
  266.      Draw_Status(sPagenum);
  267.      mvaddstr(MENULINE(iOldLine), 1, "   ");
  268.      mvaddstr(MENULINE(iNewLine), 1, "-->");
  269.      refresh();
  270.  
  271.      return(iNewGopher);
  272. }
  273.  
  274. /*
  275. ** This routine draws a numbered menu
  276. ** from a gopherdirobj
  277. ** 
  278. ** It returns the number that the user selected, or it returns
  279. ** zero if the user decided to cancel.
  280. **
  281. */
  282.  
  283. int GetMenu(gd, typedchar, redisplay)
  284.   GopherDirObj *gd;   /** where the items are **/
  285.   int          *typedchar;
  286.   boolean      redisplay;
  287. {
  288.      int ch;                /* Input character */
  289.      int iItem;             /* Display line */
  290.      static int iNewItem=1;
  291.      char sLinenum[5];      /* Used when going to a specific line */
  292.      BOOLEAN menudone = FALSE;
  293.      int numitems;
  294.      /** variables for searching **/
  295.      char search1[100];
  296.      char *search2;
  297.      int sfound;
  298.      int i;
  299.  
  300.      search1[0] = '\0'; /* search string will be remembered so init now */
  301.  
  302.      numitems = GDgetNumitems(gd);
  303.      iItem = -1;
  304.      iNewItem = GDgetCurrentItem(gd);
  305.  
  306.      if (redisplay == TRUE) {
  307.       iItem = scline(iItem, iNewItem, gd);
  308.  
  309.       /*** Draw the title ***/
  310.       CURcenterline(CursesScreen,GDgetTitle(gd), 2);
  311.       move(3+iNewItem,4);
  312.       
  313.       /* Move to the last line that we were sitting on */
  314.       refresh();
  315.      } else
  316.       iItem = GDgetCurrentItem(gd);
  317.  
  318.  
  319.      while (menudone == FALSE) {
  320.       ch = CURgetch(CursesScreen);
  321.  
  322.       switch(ch)
  323.       {
  324.       case 'j':
  325.       case '\016':
  326.       case KEY_DOWN:
  327.  
  328.            iNewItem = iItem + 1; /* Advance down the page */
  329.            break;
  330.            
  331.       case 'k':
  332.       case '\020':   /*** For those emacs dudes **/
  333.       case KEY_UP:
  334.  
  335.            iNewItem = iItem - 1; /* Back up */
  336.             break;
  337.  
  338.  
  339.       case '+':  /** Like in elm **/
  340.       case '>':  /** Like in nn  **/
  341.       case ' ':  /** Like in the pager ***/
  342.       case KEY_NPAGE:
  343.            /*** Go down a page ***/
  344.            iNewItem = iItem + (LINES -6);
  345.             if (iNewItem > numitems)
  346.              iNewItem = numitems;
  347.            break;
  348.  
  349.            
  350.       case '-':
  351.       case '<':
  352.       case KEY_PPAGE:
  353.       case 'b':      /*** Like in the pager ***/
  354.            /*** Go up a page ***/
  355.  
  356.            iNewItem = iItem - (LINES - 6);
  357.            if ( iNewItem < 0 )
  358.             iNewItem = 1;
  359.                break;
  360.  
  361.       case '1': case '2': case '3': case '4': case '5':
  362.       case '6': case '7': case '8': case '9': case '0':
  363.            
  364.            sLinenum[0] = (char) ch;
  365.            sLinenum[1] = '\0';
  366.            
  367.            if (CUROldGetOneOption(CursesScreen, "View item number: ", sLinenum) <0) {
  368.             scline(iItem, iNewItem, gd);
  369.             break;
  370.            }
  371.            
  372.            if (atoi(sLinenum) <= numitems)
  373.             iNewItem = atoi(sLinenum); /* Jump */
  374.            else {
  375.             CURBeep(CursesScreen);
  376.             break;
  377.            }
  378.  
  379.            scline(-1, iNewItem, gd);
  380.  
  381.            if (iNewItem > 0 && iNewItem <= GDgetNumitems(gd)) {
  382.             *typedchar = '\n';
  383.             GDsetCurrentItem(gd, iNewItem);
  384.             return(iItem);
  385.            }
  386.  
  387.  
  388.            break;
  389.            
  390.       case '/': 
  391.       case 'n':
  392.            sfound = 0;
  393.  
  394.            if (search1[0] == '\0' && ch == 'n') {
  395.             CursesErrorMsg("Use '/' to define a search first...");
  396.             iItem = scline(-1,iItem, gd);
  397.             break;
  398.            }
  399.  
  400.            if (search1[0] == '\0' || ch == '/')
  401.             if (CURGetOneOption(CursesScreen, "Search directory titles for", search1)<0) {
  402.              iItem = scline(-1,iItem, gd);
  403.              break;
  404.             }
  405.            if (strlen(search1) == 0) {
  406.             iItem = scline(-1, iItem, gd);
  407.             break;
  408.            }
  409.            
  410.            /*
  411.         * Start searching from next item
  412.         */
  413.  
  414.            for (i=iItem; i < numitems && sfound==0; i++) {
  415.             search2 = GSgetTitle(GDgetEntry(gd, i));
  416.             if (strcasestr(search2, search1) != NULL ) {
  417.              iNewItem = i+1;
  418.              sfound = 1;
  419.             }
  420.            }
  421.            /* if it wasn't found after the current line start
  422.           from the beginning again
  423.            */
  424.  
  425.                for ( i= 0 ; i < iItem && sfound==0;i++)  {
  426.                        search2 = GSgetTitle(GDgetEntry(gd,i));
  427.                        if (strcasestr(search2,search1) != NULL ) {
  428.                                iNewItem = i+1;
  429.                                sfound = 1;
  430.                        }
  431.                }
  432.            if (sfound == 0) {
  433.             search1[0] = '\0';
  434.             CURBeep(CursesScreen);
  435.             CursesErrorMsg("Search failed...");
  436.            }
  437.  
  438.            if (ch != 'n')
  439.             iItem = scline(-1, iNewItem, gd);
  440.                break;
  441.  
  442.       
  443.       case '\0':
  444.            break;
  445.  
  446.       default:
  447.            menudone = TRUE;
  448.            if (ch == KEY_LEFT  || ch == 'h' || ch == '\002')
  449.             ch = 'u';
  450.            if (ch == KEY_RIGHT || ch == 'l' || ch == '\006') 
  451.             ch = '\n';
  452.            *typedchar = ch;
  453.            GDsetCurrentItem(gd, iItem);
  454.            return(iItem);
  455.       }
  456.  
  457.       iItem = scline(iItem, iNewItem, gd);
  458.      
  459.       refresh();
  460.      
  461.      }
  462.  
  463.      *typedchar = ch;
  464.  
  465.      GDsetCurrentItem(gd, iItem);
  466.      return(iItem);
  467. }
  468.